package transport

import (
	"bytes"
	"context"
	pb "go-kit-service/api/video"
	"go-kit-service/pkg/endpoint"
	"go-kit-service/pkg/logger"
	"go-kit-service/pkg/service"
	"io"

	"go.uber.org/zap"
)

func (s *grpcServer) VideoList(ctx context.Context, req *pb.VideoListRequest) (*pb.VideoListResponse, error) {
	var response = &pb.VideoListResponse{
		VideoList: []*pb.VideoListResponse_VideoInfo{},
	}

	_, resp, err := s.videoList.ServeGRPC(ctx, req)
	if err != nil {
		logger.Error("grpc request videoList", zap.Error(err))
		return response, err
	}

	infoList := resp.([]service.VideoInfo)
	for _, info := range infoList {
		response.VideoList = append(response.VideoList, &pb.VideoListResponse_VideoInfo{
			Name: info.Name,
			Size: info.Size,
		})
	}

	return response, nil
}

func (s *grpcServer) UploadVideo(svr pb.Video_UploadVideoServer) error {
	var uploadVideo = endpoint.UploadVideoRequest{}

	for {
		req, err := svr.Recv()
		if err != nil {
			if err == io.EOF {
				break
			}

			return err
		}

		uploadVideo.Data = append(uploadVideo.Data, req.Data...)
		uploadVideo.Name = req.Name
	}

	_, resp, err := s.uploadVideo.ServeGRPC(context.Background(), uploadVideo)
	if err != nil {
		return err
	}

	if err := svr.SendAndClose(&pb.UploadVideoResponse{
		Message: string(resp.(endpoint.UploadVideoResponse)),
	}); err != nil {
		logger.Error("UploadVideo grpc send and close", zap.Error(err))
		return err
	}

	return nil
}

func (s *grpcServer) DownloadVideo(req *pb.DownloadVideoRequest, svr pb.Video_DownloadVideoServer) error {
	fileName := req.GetName()
	_, resp, err := s.downloadVideo.ServeGRPC(context.Background(), fileName)
	if err != nil {
		return err
	}

	reader := bytes.NewReader(resp.([]byte))
	temp := make([]byte, ChunckSize, ChunckSize)
	for {
		n, err := reader.Read(temp)
		if err != nil {
			if err == io.EOF {
				break
			}
			logger.Error("read video byte", zap.Error(err))
			return err
		}

		err = svr.Send(&pb.DownloadVideoResponse{Message: "", Data: temp[:n]})
		if err != nil {
			logger.Error("send download video grpc response", zap.Error(err))
			break
		}
	}

	return nil
}

func (s *grpcServer) ConvertVideo(svr pb.Video_ConvertVideoServer) error {
	for {
		resp, err := svr.Recv()
		if err != nil {
			if err == io.EOF {
				break
			}

			logger.Error("grpc server convert video recv data", zap.Error(err))
			return err
		}

		_, response, err := s.convertVideo.ServeGRPC(context.Background(), resp.Data)
		if err != nil {
			return err
		}

		if err := svr.Send(&pb.ConvertVideoResponse{Message: "", Data: response.([]byte)}); err != nil {
			logger.Error("grpc server convert video", zap.Error(err))
			return err
		}
	}

	return nil
}
